package roleView
{
	/**
	 * 逐帧渲染机制
	 * 如果发现所需帧未曾渲染：
	 * 1、逐步“渲染”指定帧，立即显示并将添加到临时列表中
	 * 2、当“渲染”到最后一帧时，将临时列表中的位图数据存储到正式列表中
	 * 3、清空临时列表、移除临时位图、移除侦听。
	 * 
	 * 注意，序列帧可能未渲染完毕便从场景上被删除，这种情况将继续渲染
	 * =====================================================================================================
	 * @author Kylin206
	 */
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import roleView.BitmapFrameInfo;
	import roleView.FrameBmpPool;
	import roleView.searchChild;
	
	class TemMov extends Sprite implements IMovie
	{
		static public const END_DRAW_FRAME:String = "endDrawFrame";
		private var src:DisplayObject;
		private var frames:Vector.<BitmapFrameInfo>;
		private var bmp:Bitmap;
		private var id:String;
		
		public function TemMov(id:String, src:DisplayObject)
		{
			this.src = src;
			this.id = id;
			startDrawFrame();
		}
		
		private function startDrawFrame():void
		{
			bmp = new Bitmap();
			this.addChild(bmp);
			frames = new Vector.<BitmapFrameInfo>();
			_drawFrame();
			this.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
			this.addEventListener(Event.EXIT_FRAME, exitFrameHandler);
		}
		
		private function enterFrameHandler(e:Event):void
		{
			_drawFrame();
		}
		
		private function exitFrameHandler(e:Event):void 
		{
			
			if (!bmp || this.currentFrame == this.totalFrames)
			{
				endDrawFrame();
			}
		}
		
		private function _drawFrame():void
		{
			var f_info:BitmapFrameInfo = _cacheBitmap(src, 1);
			frames.push(f_info);
			this.bmp.bitmapData = f_info.bitmapData;
			this.bmp.x = f_info.x;
			this.bmp.y = f_info.y;
		}
			
		private function endDrawFrame():void
		{
			this.removeChild(bmp);
			this.bmp = null;
			FrameBmpPool.storeBitmapFrameInfo(id, frames);
			this.removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
			this.removeEventListener(Event.EXIT_FRAME, exitFrameHandler);
			this.dispatchEvent(new Event(END_DRAW_FRAME));
		}
		
		
		//=========================================================
		/* INTERFACE roleView.IMovie */
		public function gotoAndStop(index:int):void
		{
			if (src is MovieClip)
			{
				(src as MovieClip).gotoAndStop(index);
			}
			else
			{
				
			}
		}
		
		public function gotoAndPlay(index:int):void
		{
			if (src is MovieClip)
			{
				(src as MovieClip).gotoAndPlay(index);
			}
			else
			{
				
			}
		}
		
		public function stop():void
		{
			if (src is MovieClip)
			{
				(src as MovieClip).stop();
			}
		}
		
		public function get currentFrame():int
		{
			if (src is MovieClip)
			{
				return (src as MovieClip).currentFrame;
			}
			else
			{
				return 1;
			}
		}
		
		public function get totalFrames():int
		{
			if (src is MovieClip)
			{
				return (src as MovieClip).totalFrames;
			}
			else
			{
				return 1;
			}
		}
		
		
		//=========================================================
		
		static private var pot:Point = new Point();
		
		/**
		 * 缓存单张位图
		 * @param	source				要被绘制的目标对象
		 * @param	scale				绘制的缩放值
		 * @param	transparent			是否透明
		 * @param	fillColor			填充色
		 * @return
		 */
		static private function _cacheBitmap(source:DisplayObject, scale:Number = 1, transparent:Boolean = true, fillColor:uint = 0x00000000):BitmapFrameInfo
		{
			var rect:Rectangle = source.getBounds(source);
			//var x:int = Math.round(rect.x * scale);
			//var y:int = Math.round(rect.y * scale);
			var x:int = Math.floor(rect.x * scale);
			var y:int = Math.floor(rect.y * scale);
			
			//防止 "无效的 BitmapData"异常
			if (rect.isEmpty())
			{
				rect.width = 1;
				rect.height = 1;
			}
			
			var bitData:BitmapData = new BitmapData(Math.ceil(rect.width * scale) + 1, Math.ceil(rect.height * scale) + 1, transparent, fillColor); //多一个像素，避免误差
			//bitData.draw(source, new Matrix(scale, 0, 0, scale, -x, -y), null, null, null, true);   //这里可以设置绘制bitmapData时是否平滑处理：smooth 值确定在由于 matrix 参数中指定缩放或旋转而缩放或旋转 BitmapData 对象时，是否对该对象进行平滑处理。默认值是 false。smoothing 参数只有在 source 参数是 BitmapData 对象时才适用。
			bitData.draw(source, new Matrix(scale, 0, 0, scale, -x, -y));
			
			//剔除边缘空白像素
			var realRect:Rectangle = bitData.getColorBoundsRect(0xFF000000, 0x00000000, false);
			
			if (!realRect.isEmpty() && (bitData.width != realRect.width || bitData.height != realRect.height))
			{
				
				var realBitData:BitmapData = new BitmapData(realRect.width, realRect.height, transparent, fillColor);
				realBitData.copyPixels(bitData, realRect, pot);
				
				bitData.dispose();
				bitData = realBitData;
				x += realRect.x;
				y += realRect.y;
				
			}
			
			var bitInfo:BitmapFrameInfo = new BitmapFrameInfo();
			bitInfo.x = x;
			bitInfo.y = y;
			bitInfo.bitmapData = bitData;
			
			return bitInfo;
		}
		
		/**
		 * 缓存位图动画
		 * @param	mc
		 * @param	scale
		 * @param	transparent
		 * @param	fillColor
		 * @return
		 */
		static private function _cacheBitmapMovie(mc:MovieClip, scale:Number = 1, transparent:Boolean = true, fillColor:uint = 0x00000000):Vector.<BitmapFrameInfo>
		{
			var v_bitInfo:Vector.<BitmapFrameInfo>;
			if (mc == null)
			{
				
				v_bitInfo = new Vector.<BitmapFrameInfo>(1, true);
				
				v_bitInfo[0] = _cacheBitmap(mc, scale, transparent, fillColor);
				
			}
			else
			{
				
				var i:int = 0;
				var c:int = mc.totalFrames;
				
				mc.gotoAndStop(1);
				
				v_bitInfo = new Vector.<BitmapFrameInfo>(c, true);
				
				while (i < c)
				{
					
					v_bitInfo[i] = _cacheBitmap(mc, scale, transparent, fillColor);
					
					var list_childMC:Array = searchChild(mc);
					
					mc.nextFrame();
					
					var j:int = 0;
					var k:int = list_childMC.length;
					while (j < k)
					{
						
						var childMC:MovieClip = list_childMC[j] as MovieClip;
						
						if (childMC)
						{
							if (childMC.currentFrame == childMC.totalFrames)
							{
								childMC.gotoAndStop(1);
							}
							else
							{
								childMC.nextFrame();
							}
							
						}
						
						j++;
					}
					
					i++;
				}
				
			}
			return v_bitInfo;
		}
		
		/**
		 *
		 * @param	target
		 * @param	scale
		 * @param	transparent
		 * @param	fillColor
		 * @return
		 */
		static private function cacheTarget(target:DisplayObject, scale:Number = 1, transparent:Boolean = true, fillColor:uint = 0x00000000):Vector.<BitmapFrameInfo>
		{
			if (target is MovieClip)
			{
				return _cacheBitmapMovie(target as MovieClip, scale, transparent, fillColor);
			}
			else
			{
				var v_bitInfo:Vector.<BitmapFrameInfo> = new Vector.<BitmapFrameInfo>(1, true);
				v_bitInfo[0] = _cacheBitmap(target, scale, transparent, fillColor);
				return v_bitInfo;
			}
		}
		
	}

}